<html><!-- Created using the cpp_pretty_printer from the dlib C++ library.  See http://dlib.net for updates. --><head><title>dlib C++ Library - thread_pool_ex.cpp</title></head><body bgcolor='white'><pre>
<font color='#009900'>// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
</font><font color='#009900'>/*

    This is an example illustrating the use of the thread_pool 
    object from the dlib C++ Library.


    In this example we will crate a thread pool with 3 threads and then show a
    few different ways to send tasks to the pool.
*/</font>


<font color='#0000FF'>#include</font> <font color='#5555FF'>&lt;</font>dlib<font color='#5555FF'>/</font>threads.h<font color='#5555FF'>&gt;</font>
<font color='#0000FF'>#include</font> <font color='#5555FF'>&lt;</font>dlib<font color='#5555FF'>/</font>misc_api.h<font color='#5555FF'>&gt;</font>  <font color='#009900'>// for dlib::sleep
</font><font color='#0000FF'>#include</font> <font color='#5555FF'>&lt;</font>dlib<font color='#5555FF'>/</font>logger.h<font color='#5555FF'>&gt;</font>
<font color='#0000FF'>#include</font> <font color='#5555FF'>&lt;</font>vector<font color='#5555FF'>&gt;</font>

<font color='#0000FF'>using</font> <font color='#0000FF'>namespace</font> dlib;

<font color='#009900'>// We will be using the dlib logger object to print messages in this example
</font><font color='#009900'>// because its output is timestamped and labeled with the thread that the log
</font><font color='#009900'>// message came from.  This will make it easier to see what is going on in this
</font><font color='#009900'>// example.  Here we make an instance of the logger.  See the logger
</font><font color='#009900'>// documentation and examples for detailed information regarding its use.
</font>logger <b><a name='dlog'></a>dlog</b><font face='Lucida Console'>(</font>"<font color='#CC0000'>main</font>"<font face='Lucida Console'>)</font>;


<font color='#009900'>// Here we make an instance of the thread pool object.  You could also use the
</font><font color='#009900'>// global dlib::default_thread_pool(), which automatically selects the number of
</font><font color='#009900'>// threads based on your hardware.  But here let's make our own.
</font>thread_pool <b><a name='tp'></a>tp</b><font face='Lucida Console'>(</font><font color='#979000'>3</font><font face='Lucida Console'>)</font>;

<font color='#009900'>// ----------------------------------------------------------------------------------------
</font>
<font color='#0000FF'>class</font> <b><a name='test'></a>test</b>
<b>{</b>
    <font color='#009900'>/*
        The thread_pool accepts "tasks" from the user and schedules them for 
        execution in one of its threads when one becomes available.  Each task 
        is just a request to call a function.  So here we create a class called 
        test with a few member functions, which we will have the thread pool call 
        as tasks.
    */</font>
<font color='#0000FF'>public</font>:

    <font color='#0000FF'><u>void</u></font> <b><a name='mytask'></a>mytask</b><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>
    <b>{</b>
        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>mytask start</font>";

        dlib::future<font color='#5555FF'>&lt;</font><font color='#0000FF'><u>int</u></font><font color='#5555FF'>&gt;</font> var;

        var <font color='#5555FF'>=</font> <font color='#979000'>1</font>;

        <font color='#009900'>// Here we ask the thread pool to call this-&gt;subtask() and this-&gt;subtask2().
</font>        <font color='#009900'>// Note that calls to add_task() will return immediately if there is an 
</font>        <font color='#009900'>// available thread.  However, if there isn't a thread ready then
</font>        <font color='#009900'>// add_task() blocks until there is such a thread.  Also, note that if
</font>        <font color='#009900'>// mytask() is executed within the thread pool then calls to add_task()
</font>        <font color='#009900'>// will execute the requested task within the calling thread in cases
</font>        <font color='#009900'>// where the thread pool is full.  This means it is always safe to spawn
</font>        <font color='#009900'>// subtasks from within another task, which is what we are doing here.
</font>        tp.<font color='#BB00BB'>add_task</font><font face='Lucida Console'>(</font><font color='#5555FF'>*</font><font color='#0000FF'>this</font>,<font color='#5555FF'>&amp;</font>test::subtask,var<font face='Lucida Console'>)</font>; <font color='#009900'>// schedule call to this-&gt;subtask(var) 
</font>        tp.<font color='#BB00BB'>add_task</font><font face='Lucida Console'>(</font><font color='#5555FF'>*</font><font color='#0000FF'>this</font>,<font color='#5555FF'>&amp;</font>test::subtask2<font face='Lucida Console'>)</font>;    <font color='#009900'>// schedule call to this-&gt;subtask2() 
</font>
        <font color='#009900'>// Since var is a future, this line will wait for the test::subtask task to 
</font>        <font color='#009900'>// finish before allowing us to access the contents of var.  Then var will 
</font>        <font color='#009900'>// return the integer it contains.  In this case result will be assigned 
</font>        <font color='#009900'>// the value 2 since var was incremented by subtask().
</font>        <font color='#0000FF'><u>int</u></font> result <font color='#5555FF'>=</font> var;
        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>var = </font>" <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> result;

        <font color='#009900'>// Wait for all the tasks we have started to finish.  Note that
</font>        <font color='#009900'>// wait_for_all_tasks() only waits for tasks which were started by the
</font>        <font color='#009900'>// calling thread.  So you don't have to worry about other unrelated
</font>        <font color='#009900'>// parts of your application interfering.  In this case it just waits
</font>        <font color='#009900'>// for subtask2() to finish.
</font>        tp.<font color='#BB00BB'>wait_for_all_tasks</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>;

        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>mytask end</font>" ;
    <b>}</b>

    <font color='#0000FF'><u>void</u></font> <b><a name='subtask'></a>subtask</b><font face='Lucida Console'>(</font><font color='#0000FF'><u>int</u></font><font color='#5555FF'>&amp;</font> a<font face='Lucida Console'>)</font>
    <b>{</b>
        dlib::<font color='#BB00BB'>sleep</font><font face='Lucida Console'>(</font><font color='#979000'>200</font><font face='Lucida Console'>)</font>;
        a <font color='#5555FF'>=</font> a <font color='#5555FF'>+</font> <font color='#979000'>1</font>;
        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>subtask end </font>";
    <b>}</b>

    <font color='#0000FF'><u>void</u></font> <b><a name='subtask2'></a>subtask2</b><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>
    <b>{</b>
        dlib::<font color='#BB00BB'>sleep</font><font face='Lucida Console'>(</font><font color='#979000'>300</font><font face='Lucida Console'>)</font>;
        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>subtask2 end </font>";
    <b>}</b>

<b>}</b>;

<font color='#009900'>// ----------------------------------------------------------------------------------------
</font>
<font color='#0000FF'><u>int</u></font> <b><a name='main'></a>main</b><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font> <font color='#0000FF'>try</font>
<b>{</b>
    <font color='#009900'>// tell the logger to print out everything
</font>    dlog.<font color='#BB00BB'>set_level</font><font face='Lucida Console'>(</font>LALL<font face='Lucida Console'>)</font>;


    dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>schedule a few tasks</font>";

    test taskobj;
    <font color='#009900'>// Schedule the thread pool to call taskobj.mytask().  Note that all forms of
</font>    <font color='#009900'>// add_task() pass in the task object by reference.  This means you must make sure,
</font>    <font color='#009900'>// in this case, that taskobj isn't destructed until after the task has finished
</font>    <font color='#009900'>// executing.
</font>    tp.<font color='#BB00BB'>add_task</font><font face='Lucida Console'>(</font>taskobj, <font color='#5555FF'>&amp;</font>test::mytask<font face='Lucida Console'>)</font>;

    <font color='#009900'>// This behavior of add_task() enables it to guarantee that no memory allocations
</font>    <font color='#009900'>// occur after the thread_pool has been constructed, so long as the user doesn't
</font>    <font color='#009900'>// call any of the add_task_by_value() routines.  The future object also doesn't
</font>    <font color='#009900'>// perform any memory allocations or contain any system resources such as mutex
</font>    <font color='#009900'>// objects.  If you don't care about memory allocations then you will likely find
</font>    <font color='#009900'>// the add_task_by_value() interface more convenient to use, which is shown below.
</font>


    <font color='#009900'>// If we call add_task_by_value() we pass task objects to a thread pool by value.
</font>    <font color='#009900'>// So in this case we don't have to worry about keeping our own instance of the
</font>    <font color='#009900'>// task.  Here we create a lambda function and pass it right in and everything
</font>    <font color='#009900'>// works like it should.
</font>    dlib::future<font color='#5555FF'>&lt;</font><font color='#0000FF'><u>int</u></font><font color='#5555FF'>&gt;</font> num <font color='#5555FF'>=</font> <font color='#979000'>3</font>;
    tp.<font color='#BB00BB'>add_task_by_value</font><font face='Lucida Console'>(</font>[]<font face='Lucida Console'>(</font><font color='#0000FF'><u>int</u></font><font color='#5555FF'>&amp;</font> val<font face='Lucida Console'>)</font><b>{</b>val <font color='#5555FF'>+</font><font color='#5555FF'>=</font> <font color='#979000'>7</font>;<b>}</b>, num<font face='Lucida Console'>)</font>;  <font color='#009900'>// adds 7 to num
</font>    <font color='#0000FF'><u>int</u></font> result <font color='#5555FF'>=</font> num.<font color='#BB00BB'>get</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>;
    dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>result = </font>" <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> result;   <font color='#009900'>// prints result = 10
</font>

    <font color='#009900'>// dlib also contains dlib::async(), which is essentially identical to std::async()
</font>    <font color='#009900'>// except that it launches tasks to a dlib::thread_pool (using add_task_by_value)
</font>    <font color='#009900'>// rather than starting an unbounded number of threads.  As an example, here we
</font>    <font color='#009900'>// make 10 different tasks, each assigns a different value into the elements of the
</font>    <font color='#009900'>// vector vect.
</font>    std::vector<font color='#5555FF'>&lt;</font>std::future<font color='#5555FF'>&lt;</font><font color='#0000FF'><u>unsigned</u></font> <font color='#0000FF'><u>long</u></font><font color='#5555FF'>&gt;</font><font color='#5555FF'>&gt;</font> <font color='#BB00BB'>vect</font><font face='Lucida Console'>(</font><font color='#979000'>10</font><font face='Lucida Console'>)</font>;
    <font color='#0000FF'>for</font> <font face='Lucida Console'>(</font><font color='#0000FF'><u>unsigned</u></font> <font color='#0000FF'><u>long</u></font> i <font color='#5555FF'>=</font> <font color='#979000'>0</font>; i <font color='#5555FF'>&lt;</font> vect.<font color='#BB00BB'>size</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>; <font color='#5555FF'>+</font><font color='#5555FF'>+</font>i<font face='Lucida Console'>)</font>
        vect[i] <font color='#5555FF'>=</font> dlib::<font color='#BB00BB'>async</font><font face='Lucida Console'>(</font>tp, [i]<font face='Lucida Console'>(</font><font face='Lucida Console'>)</font> <b>{</b> <font color='#0000FF'>return</font> i<font color='#5555FF'>*</font>i; <b>}</b><font face='Lucida Console'>)</font>;
    <font color='#009900'>// Print the results
</font>    <font color='#0000FF'>for</font> <font face='Lucida Console'>(</font><font color='#0000FF'><u>unsigned</u></font> <font color='#0000FF'><u>long</u></font> i <font color='#5555FF'>=</font> <font color='#979000'>0</font>; i <font color='#5555FF'>&lt;</font> vect.<font color='#BB00BB'>size</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>; <font color='#5555FF'>+</font><font color='#5555FF'>+</font>i<font face='Lucida Console'>)</font>
        dlog <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> LINFO <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> "<font color='#CC0000'>vect[</font>"<font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font>i<font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font>"<font color='#CC0000'>]: </font>" <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> vect[i].<font color='#BB00BB'>get</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>;


    <font color='#009900'>// Finally, it's usually a good idea to wait for all your tasks to complete.
</font>    <font color='#009900'>// Moreover, if any of your tasks threw an exception then waiting for the tasks
</font>    <font color='#009900'>// will rethrow the exception in the calling context, allowing you to handle it in
</font>    <font color='#009900'>// your local thread.  Also, if you don't wait for the tasks and there is an
</font>    <font color='#009900'>// exception and you allow the thread pool to be destructed your program will be
</font>    <font color='#009900'>// terminated.  So don't ignore exceptions :)
</font>    tp.<font color='#BB00BB'>wait_for_all_tasks</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font>;


    <font color='#009900'>/* A possible run of this program might produce the following output (the first
       column is the time the log message occurred and the value in [] is the thread
       id for the thread that generated the log message):

    0 INFO  [0] main: schedule a few tasks
    0 INFO  [1] main: task start
    0 INFO  [0] main: result = 10
  200 INFO  [2] main: subtask end 
  200 INFO  [1] main: var = 2
  200 INFO  [0] main: vect[0]: 0
  200 INFO  [0] main: vect[1]: 1
  200 INFO  [0] main: vect[2]: 4
  200 INFO  [0] main: vect[3]: 9
  200 INFO  [0] main: vect[4]: 16
  200 INFO  [0] main: vect[5]: 25
  200 INFO  [0] main: vect[6]: 36
  200 INFO  [0] main: vect[7]: 49
  200 INFO  [0] main: vect[8]: 64
  200 INFO  [0] main: vect[9]: 81
  300 INFO  [3] main: subtask2 end 
  300 INFO  [1] main: task end
    */</font>
<b>}</b>
<font color='#0000FF'>catch</font><font face='Lucida Console'>(</font>std::exception<font color='#5555FF'>&amp;</font> e<font face='Lucida Console'>)</font>
<b>{</b>
    std::cout <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> e.<font color='#BB00BB'>what</font><font face='Lucida Console'>(</font><font face='Lucida Console'>)</font> <font color='#5555FF'>&lt;</font><font color='#5555FF'>&lt;</font> std::endl;
<b>}</b>



</pre></body></html>